﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.WebPages;

namespace Inovout.Web.Mvc
{
    public class MobileCapableRazorViewEngine : RazorViewEngine
    {
        public string ViewModifier { get; set; }

        public Func<HttpContextBase, bool> ContextCondition { get; set; }

        public MobileCapableRazorViewEngine()
            : this("Mobile", (HttpContextBase context) => context.Request.Browser.IsMobileDevice)
        {
        }

        public MobileCapableRazorViewEngine(string viewModifier)
            : this(viewModifier, (HttpContextBase context) => context.Request.Browser.IsMobileDevice)
        {
        }

        public MobileCapableRazorViewEngine(string viewModifier, Func<HttpContextBase, bool> contextCondition)
        {
            this.ViewModifier = viewModifier;
            this.ContextCondition = contextCondition;
        }

        public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
        {
            return this.FindViewCore(controllerContext, viewName, masterName, useCache, false);
        }

        public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
        {
            return this.FindViewCore(controllerContext, partialViewName, null, useCache, true);
        }

        private ViewEngineResult FindViewCore(ControllerContext controllerContext, string viewName, string masterName, bool useCache, bool isPartialView)
        {
            if (!this.CheckMobileAndCookie(controllerContext.HttpContext))
            {
                return new ViewEngineResult(new string[0]);
            }
            string controller = controllerContext.RouteData.Values["controller"].ToString();
            string area = controllerContext.RouteData.DataTokens.ContainsKey("area") ? controllerContext.RouteData.DataTokens["area"].ToString() : string.Empty;

            string newViewName = string.Format("{0}.{1}", viewName, this.ViewModifier);
            string keyPath = Path.Combine(area, controller, newViewName);
            string cacheLocation = base.ViewLocationCache.GetViewLocation(controllerContext.HttpContext, keyPath);
            if (!useCache || string.IsNullOrWhiteSpace(cacheLocation))
            {
                string[] locationFormats = string.IsNullOrEmpty(area) ? base.ViewLocationFormats : base.AreaViewLocationFormats;
                using (IEnumerator<string> enumerator = (from currentPath in locationFormats.Select(delegate(string rootPath)
                {
                    if (!string.IsNullOrEmpty(area))
                    {
                        return string.Format(rootPath, newViewName, controller, area);
                    }
                    return string.Format(rootPath, newViewName, controller);
                })
                                                         where this.FileExists(controllerContext, currentPath)
                                                         select currentPath).GetEnumerator())
                {
                    if (enumerator.MoveNext())
                    {
                        string currentPath2 = enumerator.Current;
                        base.ViewLocationCache.InsertViewLocation(controllerContext.HttpContext, keyPath, currentPath2);
                        return isPartialView ? new ViewEngineResult(this.CreatePartialView(controllerContext, currentPath2), this) : new ViewEngineResult(this.CreateView(controllerContext, currentPath2, masterName), this);
                    }
                }
                return new ViewEngineResult(new string[0]);
            }
            if (!isPartialView)
            {
                return new ViewEngineResult(this.CreateView(controllerContext, cacheLocation, masterName), this);
            }
            return new ViewEngineResult(this.CreatePartialView(controllerContext, cacheLocation), this);
        }

        private bool CheckMobileAndCookie(HttpContextBase context)
        {
            return this.ContextCondition(context) && context.GetOverriddenBrowser().IsMobileDevice;
        }
    }
}
